#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

#define ACCOUNT_LENGTH 10

// 服务器配置信息
#define SERVER_IP "192.168.2.77"
#define SERVER_PORT 60000

// 客户端IP
#define MY_IP "192.168.2.77"
#define MY_PORT 60001

//  用户链表结构体
struct account_info
{
    char a[ACCOUNT_LENGTH + 1];     // 账号
    char user_name[30];             // 用户名
    char password[30];              // 密码
    struct sockaddr_in client_addr; // 地址结构体
};

//  通信结构体
struct message
{
    int sock_fd;             // 发送方套接字
    struct sockaddr_in addr; // 发送方地址
};

// 全局变量
int is_running = 1;

void register_user(int socket_fd)
{
    send(socket_fd, "REGISTER", 8, 0);

    // 接收响应
    char account[ACCOUNT_LENGTH + 1];
    recv(socket_fd, account, sizeof(account), 0);

    char name[30] = {0};
    char password[30] = {0};

    printf("请输入用户名: ");
    fgets(name, sizeof(name), stdin);
    name[strcspn(name, "\n")] = '\0'; // 移除换行符

    printf("请输入密码: ");
    fgets(password, sizeof(password), stdin);
    password[strcspn(password, "\n")] = '\0'; // 移除换行符

    //  构造并发送注册信息
    struct account_info reg_info;
    memset(&reg_info, 0, sizeof(reg_info));

    strncpy(reg_info.a, account, ACCOUNT_LENGTH);
    strncpy(reg_info.user_name, name, sizeof(reg_info.user_name) - 1);
    strncpy(reg_info.password, password, sizeof(reg_info.password) - 1);

    //  发送完整结构体
    send(socket_fd, &reg_info, sizeof(reg_info), 0);

    return;
}

int login_user(int socket_fd, char user_name[30])
{
    // 发送登录请求
    send(socket_fd, "LOGIN", 6, 0);

    // 发送用户名
    send(socket_fd, user_name, strlen(user_name), 0);

    // 等待服务器响应
    char response[256] = {0};
    recv(socket_fd, response, sizeof(response), 0);

    if (strcmp(response, "NEED_PASSWORD") == 0)
    {
        char password[30] = {0};
        printf("请输入密码: ");
        fgets(password, sizeof(password), stdin);
        password[strcspn(password, "\n")] = '\0';

        // 发送密码
        send(socket_fd, password, strlen(password), 0);

        // 接收登录结果
        char result[256] = {0};
        recv(socket_fd, result, sizeof(result), 0);
        printf("%s\n", result);

        if (strcmp(result, "LOGIN_SUCCESS") == 0)
        {
            return 0; // 成功
        }
        else
        {
            return 1; // 密码错误
        }
    }
    else if (strcmp(response, "USER_NOT_FOUND") == 0)
    {
        printf("用户不存在。\n");
        return 1;
    }

    return -1; // 未知错误
}

// 接收服务器消息的线程函数
void *recv_thread_func(void *arg)
{
    char buf[1024];
    int ret;

    int socket_fd = *(int *)arg;

    while (1)
    {
        // 清空缓冲区
        memset(buf, 0, sizeof(buf));

        // 接收服务器消息
        ret = recv(socket_fd, buf, sizeof(buf) - 1, 0);

        if (ret > 0)
        {
            // 成功收到消息，打印到屏幕
            printf("\n%s\n", buf);
            printf("> "); // 重新显示输入提示
            fflush(stdout);
        }
        else if (ret == 0)
        {
            // 服务器断开连接
            printf("\n服务器已断开连接\n");
            is_running = 0;
            break;
        }
        else
        {
            // 接收错误
            perror("recv error");
            is_running = 0;
            break;
        }
    }

    return NULL;
}

int main()
{
    int ret;
    pthread_t recv_thread;

    printf("===== 聊天室客户端 =====\n");

    // 1. 创建套接字
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0)
    {
        perror("socket 创建失败");
        return -1;
    }

    // 2. 设置服务器地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    // 3. 连接服务器
    ret = connect(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (ret < 0)
    {
        perror("连接服务器失败");
        close(socket_fd);
        return -1;
    }

    printf("成功连接到服务器 %s:%d\n", SERVER_IP, SERVER_PORT);

    int op = 0;
    while (1)
    {
        printf("请选择操作:1.注册, 2登陆\n");
        scanf("%d", &op);
        while (getchar() != '\n')
            ;

        struct number user = {0};

        switch (op)
        {
        case 1:
            register_user(socket_fd);
            break;
        case 2:
        {
            char UserName[30] = {0};
            printf("请输入用户名或者账号:");
            scanf("%s", UserName);
            int po = login_user(socket_fd, UserName);
            if (po == 2)
            {
                return 0;
            }
            else
                (po == 0)
                {
                    suess_login(UserName);
                }
            break;
        }
        }

        // 5. 创建接收线程
        ret = pthread_create(&recv_thread, NULL, recv_thread_func, (void *)socket_fd);
        if (ret != 0)
        {
            perror("无法创建接收线程");
            close(socket_fd);
            return -1;
        }

        printf("\n开始聊天 (输入 /exit 退出)\n");
        printf("> ");
        fflush(stdout);

        // 6. 主循环 - 处理用户输入
        while (is_running)
        {
            char input[256] = {0};
            // 获取用户输入
            if (fgets(input, sizeof(input), stdin) == NULL)
            {
                continue;
            }

            // 移除换行符
            input[strcspn(input, "\n")] = 0;

            // 处理退出命令
            if (strcmp(input, "/exit") == 0)
            {
                is_running = 0;
                break;
            }

            // 发送信息到服务器
            send(socket_fd, input, strlen(input), 0);

            // 显示输入提示
            printf("> ");
            fflush(stdout);
        }

        // 7. 清理资源
        printf("\n正在退出...\n");

        // 关闭套接字
        close(socket_fd);

        // 等待接收线程结束
        pthread_cancel(recv_thread);
        pthread_join(recv_thread, NULL);

        printf("已退出聊天室\n");
        return 0;
    }
}